/*******************************************************************************
 *
 * DSM - Distributed Search Manager
 * Developed by Milspec Research International Pty Ltd
 * 
 * $Author: gsingh $
 * $Revision: 1.2 $
 * $Date: 2004/06/01 02:46:15 $
 *
 * (c)Copyright 2004
 *    education.au limited 
 *    DEST
 *    All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this 
 * list of conditions and the following disclaimer.
 *
 * Redistributions in binary form must reproduce the above copyright notice, 
 * this list of conditions and the following disclaimer in the documentation 
 * and/or other materials provided with the distribution.
 *
 * Neither the names education.au limited, DEST nor the names of its 
 * contributors may be used to endorse or promote products derived from this 
 * software without specific prior written permission.
 *
 * To the extent permitted by law, the copyright owners of this software and 
 * its contributors:
 *
 *  (i) exclude all warranties in relation to the software; and
 * (ii) exclude liability for all losses, costs, expenses and damages arising 
 *      in any way from the use of the software whether arising from or in 
 *      relation to breach of contract, negligence or any other tort, in equity
 *      or otherwise. If the software is in breach of a warranty which is 
 *      implied by law, the copyright owners and contributors liability is
 *      limited to the replacement of the software.
 *
 *******************************************************************************
 */

package au.edu.educationau.opensource.dsm.threadpool;

/**
 * A worker class for the Thread Pool This is based on the ThreadPoolWorker
 * class written by Paul Hyde
 */
public class ThreadPoolWorker extends java.lang.Object {
	private static int nextWorkerID = 0;

	private ObjectFIFO idleWorkers;
	private int workerID;
	private ObjectFIFO handoffBox;

	private Thread internalThread;
	private volatile boolean noStopRequested;

	/**
	 * @param idleWorkers
	 */
	public ThreadPoolWorker(ObjectFIFO idleWorkers) {
		this.idleWorkers = idleWorkers;

		workerID = getNextWorkerID();
		handoffBox = new ObjectFIFO(1);

		noStopRequested = true;

		Runnable r = new Runnable() {
			public void run() {
				try {
					runWork();
				} catch (Exception x) {
					x.printStackTrace();
				}
			}
		};

		internalThread = new Thread(r);
		internalThread.start();
	}

	/** Return a new worker id */
	public static synchronized int getNextWorkerID() {
		int id = nextWorkerID;
		nextWorkerID++;
		return id;
	}

	/**
	 * Process this Runnable object
	 * 
	 * @param target
	 * @exception InterruptedException
	 */
	public void process(Runnable target) throws InterruptedException {
		handoffBox.add(target);
	}

	private void runWork() {
		while (noStopRequested) {
			try {
				idleWorkers.add(this);

				Runnable r = (Runnable) handoffBox.remove();

				runIt(r); // catches all exceptions
			} catch (InterruptedException x) {
				Thread.currentThread().interrupt(); // re-assert
			}
		}
	}

	private void runIt(Runnable r) {
		try {
			r.run();
		} catch (Exception runex) {
			// catch any and all exceptions
			runex.printStackTrace();
		} finally {
			// Clear the interrupted flag (in case it comes back set)
			// so that if the loop goes again, the
			// handoffBox.remove() does not mistakenly throw
			// an InterruptedException.
			Thread.interrupted();
		}
	}

	/** Stop the request */
	public void stopRequest() {
		noStopRequested = false;
		internalThread.interrupt();
	}

	/** Check if the thread is still alive */
	public boolean isAlive() {
		return internalThread.isAlive();
	}
}
